package org.example.netty.test.nio.netty.chat.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.example.netty.test.nio.netty.chat.bean.*;
import org.example.netty.test.nio.netty.chat.common.MessageType;
import org.example.netty.test.nio.netty.chat.common.SystemId;
import org.example.netty.test.nio.netty.chat.common.SystemMessageType;
import org.example.netty.test.nio.netty.chat.common.UserStatus;
import org.example.netty.test.nio.netty.chat.handler.ChangeMessageHandler;
import org.example.netty.test.nio.netty.chat.handler.ServerIdleHandler;
import org.example.netty.test.nio.netty.chat.protocol.MyAgreeOnMessageCodec;
import org.example.netty.test.nio.netty.chat.session.GlobalContent;
import org.example.netty.test.nio.netty.chat.session.UserSession;
import org.example.netty.test.nio.netty.chat.util.NettyChannelUtil;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import static org.example.netty.test.nio.netty.chat.common.UserType.*;

/**
 * @author zp
 * @version 1.0
 * @description: 聊天室客户端类
 * @date 2023/4/1 15:51
 */
@Slf4j
public class ChanNioClient {
    private final AtomicInteger userType = new AtomicInteger(INIT_TYPE);
    // 判断是否登入
    private final AtomicBoolean isLogin = new AtomicBoolean(false);
    // 判断是否登出
    private final AtomicBoolean isQuit = new AtomicBoolean(false);

    // 保存全局的信息传递
    private static final AtomicReference<Object> content = new AtomicReference<>();
    private final CountDownLatch loginCountDownLatch = new CountDownLatch(1);
    private final CountDownLatch countDownLatch = new CountDownLatch(1);


    public static void main(String[] args) {
        new ChanNioClient().startClient();
    }

    public void startClient() {
        // 处理IO操作
        NioEventLoopGroup bootWorkerGroup = new NioEventLoopGroup();
        // 处理耗时操作
        DefaultEventLoop workerGroup = new DefaultEventLoop();
        try {
            log.debug("客户端已启动。。。。。。。");
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(bootWorkerGroup)
                    // 设置一些客户端的 调优参数
                    // 连接超时时间 如果规定时间未连接成功（单位是毫秒） 会抛出连接超时异常 可以捕获后续处理 比如重试连接
                    // .option(ChannelOption.CONNECT_TIMEOUT_MILLIS,300)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            // 添加日志处理器
                            // pipeline.addLast("loggerHandler", new LoggingHandler(LogLevel.DEBUG));
                            // 添加字段长度解析器 解析ByteBuf的数据
                            pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 24, 4, 0, 0));
                            // 添加自定义协议的编码和解码器
                            pipeline.addLast("myAgreeOnMessageCodec", new MyAgreeOnMessageCodec());
                            // 添加输入操作 把Message 转化成对应的类型
                            // 转换类型的Handler
                            // pipeline.addLast("changeMessageHandler", new ChangeMessageHandler());
                            // 心跳监测器 一般监测写时间 时间一般是服务器监测时间的1/2 服务器是5s 这里设置3s
                            pipeline.addLast("idleStateHandler", new IdleStateHandler(0, 3, 0, TimeUnit.SECONDS));
                            // 自动发送心跳包
                            pipeline.addLast("channelDuplexHandler", new ChannelDuplexHandler() {
                                @Override
                                public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                                    if (evt instanceof IdleStateEvent) {
                                        IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
                                        if (IdleState.WRITER_IDLE.equals(idleStateEvent.state())) {
                                            // 长时间未操作 客户端自动发送心跳包
                                            // log.info("长时间未操作 发送心跳包");
                                            ctx.channel().writeAndFlush(new PingMessage());
                                        } else {
                                            super.userEventTriggered(ctx, evt);
                                        }
                                    }
                                }
                            });

                            pipeline.addLast("handler", new ChannelInboundHandlerAdapter() {
                                @Override
                                public void channelActive(ChannelHandlerContext ctx) {
                                    log.info("客户端已连接服务器");
                                    Channel channel = ctx.channel();
                                    workerGroup.execute(() -> {
                                        if (userType.get() == INIT_TYPE) {
                                            logAndRegister(ctx);
                                            try {
                                                countDownLatch.await();
                                                Thread.sleep(500);
                                            } catch (Exception e) {
                                                throw new RuntimeException(e);
                                            }
                                            if (userType.get() == REGISTER_TYPE) {
                                                logAndRegister(ctx);
                                                try {
                                                    loginCountDownLatch.await();
                                                    Thread.sleep(500);
                                                } catch (InterruptedException e) {
                                                    throw new RuntimeException(e);
                                                }
                                                runThread(ctx, channel);
                                            } else if (userType.get() == LOGIN_TYPE) {
                                                try {
                                                    loginCountDownLatch.await();
                                                    Thread.sleep(500);
                                                } catch (InterruptedException e) {
                                                    throw new RuntimeException(e);
                                                }
                                                runThread(ctx, channel);
                                            } else {
                                                System.out.println("登入注册错误！！！");
                                                System.out.println("退出登入，客户端自动关闭");
                                                channel.close();
                                            }
                                        }
                                    });
                                }

                                @Override
                                public void channelInactive(ChannelHandlerContext ctx) throws Exception {
                                    log.warn("长时间未操作 服务器自动断开");
                                    // 关闭连接自动释放资源
                                    ctx.channel().close();
                                    super.channelInactive(ctx);
                                }

                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    if (msg instanceof Message) {
                                        handlerMessage(ctx, (Message) msg);
                                    }
                                    super.channelRead(ctx, msg);
                                }
                            });

                        }
                    });
            ChannelFuture future = bootstrap.connect("127.0.0.1", 8899).sync();
            future.channel().closeFuture().sync();
            System.out.println("客户端关闭");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
            bootWorkerGroup.shutdownGracefully();
        }
        log.info("聊天室客户端已经关闭");
    }

    private void runThread(ChannelHandlerContext ctx, Channel channel) {
        if (isLogin.get()) {
            while (true) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                switch (userType.get()) {
                    case LOGIN_TYPE:
                        outSelectMenu(ctx);
                        break;
                    case USER_CHAT_TYPE:
                        JoinUserMessage joinUserMessage = (JoinUserMessage) content.get();
                        sendUserChat(ctx, joinUserMessage.getChatId());
                        break;
                    case USER_CHAT_LIST_TYPE:
                        // 所有用户列表的处理方法
                        GetALLUserMessage getAllUserMessage = (GetALLUserMessage) content.get();
                        Set<String> nameList = getAllUserMessage.getAllUserChatNames();
                        System.out.println(NettyChannelUtil.getNameList("所有用户的列表", nameList));
                        content.set(nameList);
                        userType.set(USER_CHAT_SELECT_ADD_TYPE);
                        break;
                    case USER_CHAT_SELECT_ADD_TYPE:
                        // 选择加入私聊的状态的处理方法
                        // 把数据绑定channel
                        Set<String> userNames = (Set<String>) content.get();
                        inputNameList(userNames);
                        break;
                    case JOIN_USER_TYPE:
                        // 添加私聊和发送消息
                        String addUserName = (String) content.get();
                        addUserChat(ctx, addUserName);
                        break;
                    case OUT_USER_TYPE:
                        String chatId = (String) content.get();
                        OutUserMessage outUserMessage = new OutUserMessage();
                        outUserMessage.setUserChatName(chatId);
                        outUserMessage.setSender(NettyChannelUtil.getUserClient(ctx.channel()).getUserName());
                        outUserMessage.setRecipient(chatId);
                        ctx.channel().writeAndFlush(outUserMessage);
                        break;
                    case OUT_GROUP_TYPE:
                        String groupName = (String) content.get();
                        OutGroupMessage groupMessage = new OutGroupMessage();
                        groupMessage.setGroupChatName(groupName);
                        groupMessage.setSender(Objects.requireNonNull(NettyChannelUtil.getUserClient(ctx.channel())).getUserName());
                        groupMessage.setRecipient(groupName);
                        ctx.channel().writeAndFlush(groupMessage);
                        break;
                    case GROUP_CHAT_TYPE:
                        // 群聊的处理方法
                        JoinGroupMessage joinGroupMessage = (JoinGroupMessage) content.get();
                        sendGroupChat(ctx, joinGroupMessage.getGroupName());
                        break;
                    case GROUP_CHAT_SELECT_ADD_TYPE:
                        Set<String> groupNames = (Set<String>) content.get();
                        // 把数据绑定channel
                        inputNameList(groupNames);
                        break;
                    case GROUP_CHAT_CREATE_SELECT_ADD_TYPE:
                        // 把数据绑定channel 选择创建加入群聊的类型
                        User userClient = NettyChannelUtil.getUserClient(channel);
                        assert userClient != null;
                        String userName = userClient.getUserName();
                        createGroup(ctx, userName);
                        break;
                    case GROUP_CHAT_LIST_TYPE:
                        // 所有群聊列表
                        Set<String> getAllGroupNames = (Set<String>) content.get();
                        System.out.println(NettyChannelUtil.getNameList("所有群聊的列表", getAllGroupNames));
                        content.set(getAllGroupNames);
                        userType.set(GROUP_CHAT_SELECT_ADD_TYPE);
                        break;
                    case JOIN_GROUP_TYPE:
                        // 添加群聊和发送消息
                        String addGroupName = (String) content.get();
                        addGroupChat(ctx, addGroupName);
                        break;
                    case LOG_OUT_TYPE:
                        isQuit.set(true);
                        break;
                }
                if (isQuit.get()) {
                    System.out.println("退出登入，客户端自动关闭");
                    channel.close();
                    return;
                }
                ctx.fireChannelActive();
            }
        } else {
            System.out.println("登入错误！！！");
            System.out.println("退出登入，客户端自动关闭");
            channel.close();
        }
    }

    /**
     * @description: 处理来自系统的消息
     * @author zp
     * @date: 2023/4/15 16:36
     */
    private void handlerMessage(ChannelHandlerContext ctx, Message msg) {
        AbsMessageBase messageBase = (AbsMessageBase) msg;
        if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_SYSTEM) {
            SystemMessage systemMessage = (SystemMessage) msg;
            if (systemMessage.getSystemMessageType() == SystemMessageType.LOGIN_USER_FAIL || systemMessage.getSystemMessageType() == SystemMessageType.REGISTER_USER_NAME_FAIL || systemMessage.getSystemMessageType() == SystemMessageType.LOG_IN_REPEAT_FAIL) {
                // 重置登入状态
                log.info("系统消息:【{}】", systemMessage.getSystemMessageType().getMessage());
                ctx.channel().attr(SystemId.USER_KEY).set(null);
                countDownLatch.countDown();
                loginCountDownLatch.countDown();
            } else {
                if (countDownLatch.getCount() > 0) {
                    countDownLatch.countDown();
                }

                log.info("系统消息:【{}】", systemMessage.getSystemMessageType().getMessage());
                if (SystemMessageType.SEND_USER_CHAT_FAIL.equals(systemMessage.getSystemMessageType())) {
                    log.info("系统消息:【输入任意字符 退出聊天】");
                }
                userType.set(LOGIN_TYPE);
            }
        } else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_REGISTER) {
            log.info("系统消息:【{}】", SystemMessageType.REGISTER_SUCCESS.getMessage());
            userType.set(REGISTER_TYPE);
            countDownLatch.countDown();
        } else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_LOGIN) {
            User user = NettyChannelUtil.getUserClient(ctx.channel());
            assert user != null;
            user.setStatus(UserStatus.LOGIN_STATUS);
            isLogin.set(true);
            log.info("系统消息:【{}】", SystemMessageType.LOGIN_SUCCESS.getMessage());
            if (countDownLatch.getCount() > 0) {
                countDownLatch.countDown();
            }
            loginCountDownLatch.countDown();
            userType.set(LOGIN_TYPE);
        } else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_CREATE_GROUP) {
            log.info("系统消息:【{}】", SystemMessageType.CREATE_GROUP_SUCCESS.getMessage());
            userType.set(LOGIN_TYPE);
            content.set(msg);
        } else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_ALL_GROUP_LIST) {
            GetALLGroupNameMessage getALLGroupNameMessage = (GetALLGroupNameMessage) msg;
            Set<String> allGroupNames = getALLGroupNameMessage.getAllGroupNames();
            if (allGroupNames == null || allGroupNames.size() == 0) {
                log.info("系统消息:【列表暂无数据】");
                userType.set(LOGIN_TYPE);
            } else {
                userType.set(GROUP_CHAT_LIST_TYPE);
                content.set(allGroupNames);
            }
        } else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_ALL_USER_LIST) {
            GetALLUserMessage getAllUserMessage = (GetALLUserMessage) msg;
            Set<String> allUserChatNames = getAllUserMessage.getAllUserChatNames();
            if (allUserChatNames == null || allUserChatNames.size() == 0) {
                log.info("系统消息:【列表暂无数据】");
                userType.set(LOGIN_TYPE);
            } else {
                if (getAllUserMessage.isList()) {
                    content.set(allUserChatNames);
                    System.out.println(NettyChannelUtil.getNameList("所有用户的列表", allUserChatNames));
                    userType.set(GROUP_CHAT_CREATE_SELECT_ADD_TYPE);
                } else {
                    userType.set(USER_CHAT_LIST_TYPE);
                    content.set(msg);
                }
            }
        } else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_JOIN_GROUP) {
            log.info("系统消息:【{}】", SystemMessageType.JOIN_GROUP_SUCCESS.getMessage());
            userType.set(GROUP_CHAT_TYPE);
            content.set(msg);
        } else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_JOIN_USER) {
            log.info("系统消息:【{}】", SystemMessageType.JOIN_USER_SUCCESS.getMessage());
            userType.set(USER_CHAT_TYPE);
            content.set(msg);
        } else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_OUT_GROUP) {
            log.info("系统消息:【{}】", SystemMessageType.OUT_GROUP_SUCCESS.getMessage());
            userType.set(LOGIN_TYPE);
        } else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_OUT_USER) {
            log.info("系统消息:【{}】", SystemMessageType.OUT_USER_SUCCESS.getMessage());
            userType.set(LOGIN_TYPE);
        } else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_SEND_USER) {
            SendUserMessage sendUserMessage = (SendUserMessage) msg;
            String sender = sendUserMessage.getSender();
            System.out.println("【" + sender + "】:" + sendUserMessage.getMessage());
            content.set(msg);
            userType.set(USER_CHAT_TYPE);
        } else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_SEND_GROUP) {
            SendGroupMessage sendGroupMessage = (SendGroupMessage) msg;
            String sender = sendGroupMessage.getSender();
            System.out.println("【" + sender + "】:" + sendGroupMessage.getMessage());
            content.set(msg);
            userType.set(GROUP_CHAT_TYPE);
        } else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_LOG_OUT) {
            LogoutMessage logoutMessage = (LogoutMessage) messageBase;
            String userName = logoutMessage.getUserName();
            content.set(userName);
            userType.set(LOG_OUT_TYPE);
        }else if (messageBase.getMessageType() == MessageType.MESSAGE_TYPE_RPC_RESPONSE) {
            RpcResponse response = (RpcResponse) messageBase;
            log.info("打印RPC返回的消息：[{}]",response);
            userType.set(LOGIN_TYPE);
        }
    }

    /**
     * @param nameList
     * @description: 处理不同消息的handler请求
     * @author zp
     * @date: 2023/4/29 16:07
     */
    private void inputNameList(Set<String> nameList) {
        String next;
        int count = 0;
        do {
            System.out.println("选择加入聊天名称：");
            Scanner scanner = new Scanner(System.in);
            next = scanner.nextLine();
            if (StringUtil.isNullOrEmpty(next)) {
                count++;
                System.out.println("输入有误");
                continue;
            } else if (SystemId.QUITE.equals(next)) {
                userType.set(LOGIN_TYPE);
                break;
            }
            if (!nameList.contains(next)) {
                count++;
                System.out.println("输入有误");
                continue;
            }
            if (count == 4) {
                System.out.println("输入错误 超过次数 回到菜单");
                break;
            }
            break;
        } while (true);
        if (userType.get() == USER_CHAT_SELECT_ADD_TYPE) {
            userType.set(JOIN_USER_TYPE);
            content.set(next);
        } else if (userType.get() == GROUP_CHAT_SELECT_ADD_TYPE) {
            userType.set(JOIN_GROUP_TYPE);
            content.set(next);
        }


    }

    /**
     * @param ctx
     * @param groupName
     * @description: 发送群消息
     * @author zp
     * @date: 2023/4/29 16:54
     */
    private void sendGroupChat(ChannelHandlerContext ctx, String groupName) {
        System.out.println("下面可以发送群聊的消息");
        // 交给 Netty的多线程处理
        String message;
        Scanner scanner = new Scanner(System.in);
        do {
            message = scanner.nextLine();
            if (StringUtil.isNullOrEmpty(message)) {
                System.out.println("不能输入空字符串 请重新输入！！！");
                continue;
            }
            if (SystemId.QUITE.equals(message)) {
                content.set(groupName);
                userType.set(OUT_GROUP_TYPE);
                break;
            }

            if (userType.get() == LOGIN_TYPE) {
                break;
            }
            User userClient = NettyChannelUtil.getUserClient(ctx.channel());
            assert userClient != null;
            SendGroupMessage sendGroupMessage = new SendGroupMessage();
            sendGroupMessage.setGroupName(groupName);
            sendGroupMessage.setSender(userClient.getUserName());
            sendGroupMessage.setRecipient(SystemId.SERVER_ID);
            sendGroupMessage.setContent(message);
            ctx.channel().writeAndFlush(sendGroupMessage);
        } while (!SystemId.QUITE.equals(message));
    }

    /**
     * @param ctx
     * @description: 加入群聊
     * @author zp
     * @date: 2023/4/29 16:01
     */
    private static void addGroupChat(ChannelHandlerContext ctx, String userName) {
        User userClient = NettyChannelUtil.getUserClient(ctx.channel());
        assert userClient != null;
        JoinGroupMessage joinGroupMessage = new JoinGroupMessage();
        joinGroupMessage.setSender(userClient.getUserName());
        joinGroupMessage.setRecipient(SystemId.SERVER_ID);
        joinGroupMessage.setGroupName(userName);
        ctx.channel().writeAndFlush(joinGroupMessage);
    }

    /**
     * @param ctx
     * @description: 发送加入私聊的请求
     * @author zp
     * @date: 2023/4/23 19:35
     */
    private static void addUserChat(ChannelHandlerContext ctx, String userName) {
        JoinUserMessage joinUserMessage = new JoinUserMessage();
        joinUserMessage.setChatId(userName);
        User userClient = NettyChannelUtil.getUserClient(ctx.channel());
        assert userClient != null;
        joinUserMessage.setCreateBuildUserName(userClient.getUserName());
        joinUserMessage.setChatId(userName);
        joinUserMessage.setByUserName(userName);
        joinUserMessage.setSender(userClient.getUserId());
        joinUserMessage.setRecipient(SystemId.SERVER_ID);
        ctx.channel().writeAndFlush(joinUserMessage);
    }

    /**
     * @param ctx
     * @param chatId
     * @description: 发送私聊的消息
     * @author zp
     * @date: 2023/4/23 19:35
     */
    private void sendUserChat(ChannelHandlerContext ctx, String chatId) {
        System.out.println("下面可以发送私聊的消息");
        // 交给 Netty的多线程处理
        String message;
        Scanner scanner = new Scanner(System.in);
        do {
            message = scanner.nextLine();
            if (StringUtil.isNullOrEmpty(message)) {
                System.out.println("不能输入空字符串 请重新输入！！！");
                continue;
            }

            if (SystemId.QUITE.equals(message)) {
                content.set(chatId);
                userType.set(OUT_USER_TYPE);
                break;
            }

            if (userType.get() == LOGIN_TYPE) {
                break;
            }

            SendUserMessage sendUserMessage = new SendUserMessage();
            sendUserMessage.setUserChatId(chatId);
            sendUserMessage.setSender(Objects.requireNonNull(NettyChannelUtil.getUserClient(ctx.channel())).getUserName());
            sendUserMessage.setRecipient(chatId);
            sendUserMessage.setContent(message);
            ctx.channel().writeAndFlush(sendUserMessage);
        } while (!SystemId.QUITE.equals(message));
    }


    /**
     * @description: 输出系统菜单
     * @author zp
     * @date: 2023/4/15 16:31
     */
    private void outSelectMenu(ChannelHandlerContext ctx) {
        do {
            int choose;
            Scanner input = new Scanner(System.in);
            System.out.println("****************************");
            System.out.println("********1、查看所有聊天成员*********");
            System.out.println("********2、查看所有群聊*********");
            System.out.println("********3、创建群聊*********");
            System.out.println("********4、测试自定义RPC协议*********");
            System.out.println("********5、登出*********");

            System.out.println("********备注：输入“#” 可以在其他页面调出菜单！！！*********");
            System.out.println("****************************");
            System.out.print("请选择：");
            String next = input.next();
            boolean matches = next.matches("^[1-5]$");
            if (!matches) {
                System.out.println("输入错误请重新输入！！！");
                continue;
            } else {
                choose = Integer.parseInt(next);
            }
            Channel channel = ctx.channel();
            User user = NettyChannelUtil.getUserClient(channel);
            assert user != null;
            String userName = user.getUserName();
            // 查看所有聊天成员
            if (1 == choose) {
                GetALLUserMessage getALLUserMessage = new GetALLUserMessage();
                getALLUserMessage.setSender(userName);
                getALLUserMessage.setRecipient(SystemId.SERVER_ID);
                ctx.channel().writeAndFlush(getALLUserMessage);
                break;
            } else if (2 == choose) {
                GetALLGroupNameMessage getALLGroupNameMessage = new GetALLGroupNameMessage();
                getALLGroupNameMessage.setSender(userName);
                getALLGroupNameMessage.setRecipient(SystemId.SERVER_ID);
                ctx.channel().writeAndFlush(getALLGroupNameMessage);
                break;
            } else if (3 == choose) {
                GetALLUserMessage getAllUserMessage = new GetALLUserMessage();
                getAllUserMessage.setSender(userName);
                getAllUserMessage.setRecipient(SystemId.SERVER_ID);
                getAllUserMessage.setList(true);
                ctx.channel().writeAndFlush(getAllUserMessage);
                break;
            } else if (4 == choose) {
                RpcRequest rpcRequest = new RpcRequest();
                rpcRequest.setRequestId("110");
                rpcRequest.setParameters(new Object[]{"张三","你好"});
                rpcRequest.setParameterTypes(new Class<?>[] {String.class,String.class});
                rpcRequest.setMethodName("sayHello");
                rpcRequest.setClassName("org.example.netty.test.nio.netty.chat.service.UserService");
                ctx.channel().writeAndFlush(rpcRequest);
                break;
            } else if (5 == choose) {
                LogoutMessage build = LogoutMessage.build(userName);
                build.setSender(userName);
                build.setRecipient(SystemId.SERVER_ID);
                ctx.channel().writeAndFlush(build);
                break;
            }
        } while (true);
    }

    /**
     * @description: 创建群聊
     * @author zp
     * @date: 2023/4/23 20:15
     */
    private void createGroup(ChannelHandlerContext ctx, String userName) {
        String next;
        Set<String> groupUserNames = (Set<String>) content.get();
        if (groupUserNames == null || groupUserNames.size() < 2) {
            log.info("系统消息：【未获取到用户列表或者用户数量不足无法组成群聊 系统自动退出】");
            userType.set(LOGIN_TYPE);
        } else {
            do {
                System.out.println("输入群名称：");
                Scanner scanner = new Scanner(System.in);
                next = scanner.next();
                if (StringUtil.isNullOrEmpty(next)) {
                    System.out.println("输入错误请重新输入！！！");
                    continue;
                }

                if (SystemId.QUITE.equals(next)) {
                    userType.set(LOGIN_TYPE);
                    break;
                }
                log.debug("输入创建的群名称：[{}]", next);
                CreateGroupMessage createGroupMessage = new CreateGroupMessage();
                createGroupMessage.setSender(userName);
                createGroupMessage.setRecipient(SystemId.SERVER_ID);
                createGroupMessage.setGroupName(next);
                System.out.println("（输入用户名称 使用 ',' 分割 示例zhangsan,lisi,wangwu,.....）  最少不能少于两人 否则创建群失败");
                System.out.println("选择需要加入的用户的名称列表：");
                next = scanner.next();
                String[] userNames = next.split(",");
                Set<String> userNameSet = new HashSet<>(Arrays.asList(userNames));

                log.debug("输入创建的群成员名称列表：[{}]", userNameSet);

                if (userNameSet.size() < 2 || !checkUserNameList(userNameSet)) {
                    log.info("系统消息：【输入数据错误 请重新输入】");
                    continue;
                }
                log.debug("获取的用户名称列表【{}】", userNameSet);
                createGroupMessage.setJoinGroupUserNames(userNameSet);
                ctx.channel().writeAndFlush(createGroupMessage);
                break;
            } while (true);
        }

    }

    /**
     * @param userNameSet
     * @return boolean
     * @description: 校验输入的用户数据是否有效
     * @author zp
     * @date: 2023/4/24 19:33
     */
    private boolean checkUserNameList(Set<String> userNameSet) {
        Set<String> userNameList = (Set<String>) content.get();
        log.debug("校验输入的用户数据是否有效 用户名集合[{}]", userNameList);
        if (userNameList == null || userNameList.size() == 0) {
            return false;
        }
        for (String userName : userNameSet) {
            if (!userNameList.contains(userName)) {
                return false;
            }
        }
        return true;
    }

    /**
     * @param ctx
     * @description: 处理登入和注册
     * @author zp
     * @date: 2023/4/15 16:16
     */
    private void logAndRegister(ChannelHandlerContext ctx) {
        String next;
        do {
            System.out.println("请选择：");
            System.out.println("1、：登入");
            System.out.println("2、：注册");
            Scanner scanner = new Scanner(System.in);
            next = scanner.next();
            boolean matches = next.matches("^[1-2]$");
            if (!matches) {
                System.out.println("输入错误请,请重新输入！！！");
                continue;
            }
            if ("1".equals(next)) {
                System.out.println("请输入用户名:");
                String username = scanner.next();
                System.out.println("请输入密码:");
                String password = scanner.next();
                User user = new User();
                user.setUserName(username);
                user.setPassword(password);
                user.setStatus(UserStatus.INIT_STATUS);
                LoginMessage loginMessage = LoginMessage.buildLogin(username, password);
                // 绑定Channel信息 发送登入请求之后
                ctx.channel().attr(SystemId.USER_KEY).set(user);
                log.info("登入调用");
                ctx.channel().writeAndFlush(loginMessage);
                break;
            } else if ("2".equals(next)) {
                System.out.println("请输入用户名:");
                String username = scanner.next();
                System.out.println("请输入密码:");
                String password = scanner.next();
                RegisterMessage registerMessage = RegisterMessage.buildRegister(username, password);
                log.info("注册调用");
                ctx.channel().writeAndFlush(registerMessage);
                break;
            }
        } while (!SystemId.QUITE.equals(next));
    }
}
